package natsjs

import (
	"fmt"
	"time"

	"go-zero-admin/pkg/tool"

	"github.com/nats-io/nats.go"
	"github.com/zeromicro/go-zero/core/logx"
)

func InitNatsConn(connConfig *NatsConnectProperties) (*nats.Conn, nats.JetStreamContext, *nats.EncodedConn) {
	// 创建nats连接
	var optionList []nats.Option
	optionList = append(optionList, nats.RetryOnFailedConnect(connConfig.IsRetry))
	if connConfig.MaxReconnect != 0 {
		optionList = append(optionList, nats.MaxReconnects(connConfig.MaxReconnect))
	}
	if connConfig.ReconnectWait != 0 {
		optionList = append(optionList, nats.ReconnectWait(time.Duration(connConfig.ReconnectWait)*time.Second))
	}
	if connConfig.DisconnectErrHandler != nil {
		nats.DisconnectErrHandler(connConfig.DisconnectErrHandler)
	}
	if connConfig.ReconnectHandler != nil {
		nats.ReconnectHandler(connConfig.ReconnectHandler)
	}
	if connConfig.ClosedHandler != nil {
		nats.ClosedHandler(connConfig.ClosedHandler)
	}
	nc, err := nats.Connect(connConfig.Servers, optionList...)
	if err != nil {
		logx.Errorf(tool.GetErrMsgHeaderFormat("MQ-RPC-NATS-ERR", "init nats connect"), err)

		fmt.Printf("【MQ-RPC-NATS-ERR】Failed to start mq's rpc server: nats connect init failed" + "\n")

		return nil, nil, nil
	}

	// 创建jetStream连接
	var jsOptList []nats.JSOpt
	if connConfig.PublishAsyncMaxPending != 0 {
		jsOptList = append(jsOptList, nats.PublishAsyncMaxPending(connConfig.PublishAsyncMaxPending))
	}
	js, err := nc.JetStream(jsOptList...)
	if err != nil {
		logx.Errorf(tool.GetErrMsgHeaderFormat("MQ-RPC-NATS-ERR", "init nats jetStream connect"), err)

		fmt.Printf("【MQ-RPC-NATS-ERR】Failed to start mq's rpc server: nats jetStream connect init failed" + "\n")

		return nil, nil, nil
	}

	// 创建Encoded连接
	en, err := nats.NewEncodedConn(nc, connConfig.EncType)
	if err != nil {
		logx.Errorf(tool.GetErrMsgHeaderFormat("MQ-RPC-NATS-ERR", "init nats encoded connect"), err)

		fmt.Printf("【MQ-RPC-NATS-ERR】Failed to start mq's rpc server: nats encoded connect init failed" + "\n")

		return nil, nil, nil
	}

	fmt.Printf("【MQ-RPC-NATS-SUCCESS】Starting mq's rpc server: nats init successed" + "\n")
	return nc, js, en
}

// NatsConnectProperties nats连接属性
type NatsConnectProperties struct {
	Servers                string                         // 连接地址，可以集群，以逗号分隔
	IsRetry                bool                           // 是否重试连接
	MaxReconnect           int                            // 最大连接次数
	ReconnectWait          int64                          // 重新连接时间
	PublishAsyncMaxPending int                            // 异步发布最大挂起数量
	EncType                string                         // 编码连接编码格式
	DisconnectErrHandler   func(nc *nats.Conn, err error) // 断开错误处理程序
	ReconnectHandler       func(nc *nats.Conn)            // 重新连接处理程序
	ClosedHandler          func(nc *nats.Conn)            // 关闭处理程序
}
